package com.example.a_java.util;

import com.example.a_java.common.BusinessException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * Excel导出工具�?
 */
public class ExcelUtil {
    
    private static final Logger logger = LoggerFactory.getLogger(ExcelUtil.class);
    
    /**
     * 导出Excel
     *
     * @param response  响应对象
     * @param fileName  文件�?
     * @param sheetName sheet�?
     * @param list      数据集合
     * @param headers   表头
     * @param fields    属性字�?
     * @param <T>       泛型
     */
    public static <T> void exportExcel(HttpServletResponse response, String fileName, String sheetName,
                                     List<T> list, String[] headers, String[] fields) {
        try {
            // 创建工作�?
            Workbook workbook = new XSSFWorkbook();
            // 创建sheet
            Sheet sheet = workbook.createSheet(sheetName);
            
            // 创建表头
            Row headerRow = sheet.createRow(0);
            CellStyle headerStyle = createHeaderStyle(workbook);
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
                // 设置列宽
                sheet.setColumnWidth(i, 4000);
            }
            
            // 填充数据
            CellStyle dataStyle = createDataStyle(workbook);
            if (!CollectionUtils.isEmpty(list)) {
                for (int i = 0; i < list.size(); i++) {
                    Row dataRow = sheet.createRow(i + 1);
                    T item = list.get(i);
                    for (int j = 0; j < fields.length; j++) {
                        Cell cell = dataRow.createCell(j);
                        setCellValue(cell, item, fields[j]);
                        cell.setCellStyle(dataStyle);
                    }
                }
            }
            
            // 设置响应�?
            setResponseHeader(response, fileName);
            
            // 输出文件
            OutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
            workbook.close();
        } catch (Exception e) {
            logger.error("Excel导出失败", e);
            throw new BusinessException("Excel导出失败：" + e.getMessage());
        }
    }
    
    /**
     * 创建表头样式
     */
    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        // 水平居中
        style.setAlignment(HorizontalAlignment.CENTER);
        // 垂直居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        // 设置背景�?
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 设置字体
        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        return style;
    }
    
    /**
     * 创建数据样式
     */
    private static CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        // 水平居中
        style.setAlignment(HorizontalAlignment.CENTER);
        // 垂直居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }
    
    /**
     * 设置单元格�?
     */
    private static <T> void setCellValue(Cell cell, T item, String fieldName) {
        try {
            Field field = getField(item.getClass(), fieldName);
            if (field != null) {
                field.setAccessible(true);
                Object value = field.get(item);
                if (value != null) {
                    if (value instanceof LocalDateTime) {
                        cell.setCellValue(((LocalDateTime) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    } else if (value instanceof Date) {
                        cell.setCellValue((Date) value);
                    } else if (value instanceof Integer || value instanceof Long) {
                        cell.setCellValue(Double.parseDouble(value.toString()));
                    } else {
                        cell.setCellValue(value.toString());
                    }
                }
            }
        } catch (Exception e) {
            logger.error("设置单元格值失败", e);
        }
    }
    
    /**
     * 获取类的字段（包括父类）
     */
    private static Field getField(Class<?> clazz, String fieldName) {
        Field field = null;
        try {
            field = clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null) {
                field = getField(superClass, fieldName);
            }
        }
        return field;
    }
    
    /**
     * 设置响应�?
     */
    private static void setResponseHeader(HttpServletResponse response, String fileName) throws IOException {
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } catch (Exception e) {
            fileName = UUID.randomUUID().toString() + ".xlsx";
        }
        
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
    }
} 
